

// printcds.c 
//
// created by Mike Podanoffsky
//            "Dissecting DOS"
// 
// make instructions:
// 
//    cl /AL printcds.c
// 
// 
// 

#include <string.h>
#include <stdio.h>
#include <dos.h>


// where DOS keeps the NULL driver.

#define _RXDOS_pCDS                 0x003C
#define _RXDOS_bLastDrive           0x0047
#define SIZEOFCDS_v3                81        

// DOS CDS Structure

#pragma pack(1)
typedef struct _CDS {

   char        _cdsActualDirectory[ 67 ];
   int         _cdsFlags;
   void      * _cdsPtrToDPB;
   int         _cdsStartClusterDir;
   int         _cdsNetPadding1;
   int         _cdsNetPadding2;
   int         _cdsNonSubstOffset;
   char        _cdsUndefined1;
   void      * _cdsPtrtoIFSDriver;
   int         _cdsUndefined2;

   } CDS, * LPCDS;
#pragma pack()

// DOS Device Header Flags

#define _CDS_NETWORKEDDRIVE     0x8000
#define _CDS_PHYSICALDRIVE      0x4000
#define _CDS_JOINEDDRIVE        0x2000
#define _CDS_SUBSTDRIVE         0x1000

///////////////////////////////////////////////////////////////

typedef struct _messages {

   int         Flags;
   char      * Message;

   }  MESSAGES;

MESSAGES Messages[] = {

   { _CDS_NETWORKEDDRIVE,     "Networked drive"            },
   { _CDS_PHYSICALDRIVE,      "Physical drive"             },
   { _CDS_JOINEDDRIVE,        "Joined drive"               },
   { _CDS_SUBSTDRIVE,         "Subst drive"                },

   };

///////////////////////////////////////////////////////////////
static void printFlags( LPCDS lpCDS )
{

   int k;
   
   for ( k = 0; k < sizeof( Messages )/sizeof( MESSAGES ); ++k )
      {
      if ( lpCDS-> _cdsFlags & Messages[ k ]. Flags )
         printf( "\n %s", Messages[ k ]. Message );

      }

   printf( "\n" );
}

///////////////////////////////////////////////////////////////
main()
{

   union _REGS r;
   struct _SREGS s;

   LPCDS *lpCDS = NULL;
   LPCDS  lpCurrentCDS = NULL;
   char  *lpLastDrive;
   int    k, LastDrive = 0;
   int    sizeofCDS = sizeof( CDS );

   // get DOS Version

   r.h.ah = 0x30;                      // get DOS version 
   _intdosx( &r, &r, &s );

   if ( r. h. al == 0x3 )
      sizeofCDS = SIZEOFCDS_v3;

   if ( r. h. al < 0x3 )
      {
      printf( "\n DOS Versions prior to 3.0 did not have a CDS structure.\n\n" );
      exit(1);
      }

   // get DOS List of Lists

   r.h.ah = 0x52;                      // use undoc function 52
   _intdosx( &r, &r, &s );             // es contains seg address of DOS

   FP_SEG( lpLastDrive ) = FP_SEG( lpCDS ) = s.es;
   FP_OFF( lpCDS )       = _RXDOS_pCDS;
   FP_OFF( lpLastDrive ) = _RXDOS_bLastDrive;

   printf ( "\n\n" );
   printf ( " Current Directory Structure\n" );
   printf ( " ---------------------------------------------------\n" );


   // then we loop through the CDS structure

   lpCurrentCDS = *lpCDS;
   LastDrive = (int )(*lpLastDrive);

   for ( k = 0; k < LastDrive; ++k )
      {
      printf("\n %-67s", lpCurrentCDS-> _cdsActualDirectory );

      if ( lpCurrentCDS-> _cdsStartClusterDir == -1 )
         printf("\n Cluster: Not Initialized" );

      else
         printf("\n Cluster: %4x ", lpCurrentCDS-> _cdsStartClusterDir );

      printf("\n NonSubstOffset: %4d", lpCurrentCDS-> _cdsNonSubstOffset );

      printFlags( lpCurrentCDS );
      FP_OFF( lpCurrentCDS ) += sizeofCDS;
      }


}
